home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
gnu
/
nethack.lha
/
nethack-3.1
/
src
/
bones.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-08
|
9KB
|
386 lines
/* SCCS Id: @(#)bones.c 3.1 93/01/07 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985,1993. */
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
#include "lev.h"
#ifdef MFLOPPY
extern char bones[]; /* from files.c */
extern long bytes_counted;
#endif
static boolean FDECL(no_bones_level, (d_level *));
#ifdef TUTTI_FRUTTI
static void FDECL(goodfruit, (int));
#endif
static void FDECL(resetobjs,(struct obj *,BOOLEAN_P));
static void FDECL(drop_upon_death, (struct monst *, struct obj *));
static boolean
no_bones_level(lev)
d_level *lev;
{
extern d_level save_dlevel; /* in do.c */
s_level *sptr;
if (ledger_no(&save_dlevel)) assign_level(lev, &save_dlevel);
return (((sptr = Is_special(lev)) && !sptr->boneid)
|| !dungeons[lev->dnum].boneid
/* no bones on the last or multiway branch levels */
/* in any dungeon (level 1 isn't multiway). */
|| Is_botlevel(lev) || (Is_branchlev(lev) && lev->dlevel > 1)
/* no bones in the invocation level */
|| (In_hell(lev) && lev->dlevel == dunlevs_in_dungeon(lev) - 1)
);
}
#ifdef TUTTI_FRUTTI
static void
goodfruit(id)
int id;
{
register struct fruit *f;
for(f=ffruit; f; f=f->nextf) {
if(f->fid == -id) {
f->fid = id;
return;
}
}
}
#endif
static void
resetobjs(ochain,restore)
struct obj *ochain;
boolean restore;
{
struct obj *otmp;
for (otmp = ochain; otmp; otmp = otmp->nobj) {
if (otmp->cobj)
resetobjs(otmp->cobj,restore);
if (((otmp->otyp != CORPSE || otmp->corpsenm < PM_ARCHEOLOGIST)
&& otmp->otyp != STATUE)
&& (!otmp->oartifact ||
(exist_artifact(otmp->otyp,ONAME(otmp)) && restore))) {
otmp->oartifact = 0;
otmp->onamelth = 0;
*ONAME(otmp) = '\0';
} else if (otmp->oartifact && restore)
artifact_exists(otmp,ONAME(otmp),TRUE);
if (!restore) {
/* resetting the o_id's after getlev has carefully
* created proper new ones via restobjchn is a Bad
* Idea */
otmp->o_id = 0;
if(objects[otmp->otyp].oc_uses_known) otmp->known = 0;
otmp->dknown = otmp->bknown = 0;
otmp->rknown = 0;
otmp->invlet = 0;
#ifdef TUTTI_FRUTTI
if(otmp->otyp == SLIME_MOLD) goodfruit(otmp->spe);
#endif
#ifdef MAIL
if (otmp->otyp == SCR_MAIL) otmp->spe = 1;
#endif
#ifdef POLYSELF
if (otmp->otyp == EGG) otmp->spe = 0;
#endif
if(otmp->otyp == AMULET_OF_YENDOR) {
/* no longer the actual amulet */
otmp->otyp = FAKE_AMULET_OF_YENDOR;
curse(otmp);
}
if(otmp->otyp == CANDELABRUM_OF_INVOCATION) {
if(otmp->spe > 0) { /* leave candles, if any */
otmp->otyp = WAX_CANDLE;
otmp->age = 50L; /* assume used */
otmp->quan = (long)otmp->spe;
otmp->lamplit = 0;
otmp->spe = 0;
} else obfree(otmp, (struct obj *)0);
}
if(otmp->otyp == BELL_OF_OPENING) otmp->otyp = BELL;
if(otmp->otyp == SPE_BOOK_OF_THE_DEAD) {
otmp->otyp = SPE_MAGIC_MISSILE +
rn2(SPE_BLANK_PAPER -
SPE_MAGIC_MISSILE + 1);
curse(otmp);
}
}
}
}
static void
drop_upon_death(mtmp, cont)
struct monst *mtmp;
struct obj *cont;
{
struct obj *otmp = invent;
while(otmp) {
otmp->owornmask = 0;
otmp->lamplit = 0;
#ifdef TUTTI_FRUTTI
if(otmp->otyp == SLIME_MOLD) goodfruit(otmp->spe);
#endif
if(rn2(5)) curse(otmp);
if(!mtmp && !cont) place_object(otmp, u.ux, u.uy);
if(!otmp->nobj) {
if (mtmp) {
otmp->nobj = mtmp->minvent;
mtmp->minvent = invent;
} else if (cont) {
otmp->nobj = cont->cobj;
cont->cobj = invent;
} else {
otmp->nobj = fobj;
fobj = invent;
}
invent = 0; /* superfluous */
break;
}
otmp = otmp->nobj;
}
if(u.ugold) {
if (mtmp) mtmp->mgold = u.ugold;
else mkgold(u.ugold, u.ux, u.uy);
}
}
/* save bones and possessions of a deceased adventurer */
void
savebones()
{
register int fd, x, y;
register struct trap *ttmp;
register struct monst *mtmp, *mtmp2;
#ifdef TUTTI_FRUTTI
struct fruit *f;
#endif
char *bonesid;
if(ledger_no(&u.uz) <= 0 || ledger_no(&u.uz) > maxledgerno()) return;
if(no_bones_level(&u.uz)) return; /* no bones for specific levels */
if(!rn2(1 + (depth(&u.uz)>>2)) /* fewer ghosts on low levels */
#ifdef WIZARD
&& !wizard
#endif
) return;
#ifdef EXPLORE_MODE
/* don't let multiple restarts generate multiple copies of objects
* in bones files */
if(discover) return;
#endif
fd = open_bonesfile(&u.uz, &bonesid);
if (fd >= 0) {
(void) close(fd);
compress_bonesfile();
#ifdef WIZARD
if(wizard)
pline("Bones file already exists.");
#endif
return;
}
#ifdef WALKIES
unleash_all();
#endif
/* in case these characters are not in their home bases */
mtmp2 = fmon;
while((mtmp = mtmp2)) {
mtmp2 = mtmp->nmon;
if(mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA]) mongone(mtmp);
}
#ifdef TUTTI_FRUTTI
/* mark all fruits as nonexistent; when we come to them we'll mark
* them as existing (using goodfruit())
*/
for(f=ffruit; f; f=f->nextf) f->fid = -f->fid;
#endif
/* check iron balls separately--maybe they're not carrying it */
if (uball) uball->owornmask = uchain->owornmask = 0;
/* dispose of your possessions, usually cursed */
if (u.ugrave_arise == -2) {
struct obj *otmp;
/* embed your possessions in your statue */
otmp = mk_named_object(STATUE,
#ifdef POLYSELF
u.mtimedone ? uasmon :
#endif
player_mon(),
u.ux, u.uy, plname,
(int)strlen(plname));
if (!otmp) return;
drop_upon_death(mtmp = (struct monst *)0, otmp);
} else if (u.ugrave_arise == -1) {
/* drop everything */
drop_upon_death((struct monst *)0, (struct obj *)0);
/* trick makemon() into allowing monster creation
* on your location
*/
in_mklev = TRUE;
mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy);
in_mklev = FALSE;
if (!mtmp) return;
Strcpy((char *) mtmp->mextra, plname);
} else {
/* give your possessions to the monster you become */
in_mklev = TRUE;
mtmp = makemon(&mons[u.ugrave_arise], u.ux, u.uy);
in_mklev = FALSE;
if (!mtmp) return;
mtmp = christen_monst(mtmp, plname);
newsym(u.ux, u.uy);
Your("body rises from the dead as %s...",
an(mons[u.ugrave_arise].mname));
display_nhwindow(WIN_MESSAGE, FALSE);
drop_upon_death(mtmp, (struct obj *)0);
#ifdef MUSE
m_dowear(mtmp, TRUE);
#endif
}
if (mtmp) {
mtmp->m_lev = (u.ulevel ? u.ulevel : 1);
mtmp->mhp = mtmp->mhpmax = u.uhpmax;
mtmp->msleep = 1;
}
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
resetobjs(mtmp->minvent,FALSE);
mtmp->m_id = 0;
mtmp->mlstmv = 0L;
if(mtmp->mtame) mtmp->mtame = mtmp->mpeaceful = 0;
}
for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
if(ttmp->ttyp == MAGIC_PORTAL) deltrap(ttmp);
ttmp->tseen = 0;
}
resetobjs(fobj,FALSE);
/* Clear all memory from the level. */
for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++) {
levl[x][y].seen = levl[x][y].waslit = 0;
levl[x][y].glyph = cmap_to_glyph(S_stone);
}
fd = create_bonesfile(&u.uz, &bonesid);
if(fd < 0) {
#ifdef WIZARD
if(wizard)
pline("Cannot create bones file - create failed");
#endif
return;
}
bufon(fd);
#ifdef MFLOPPY /* check whether there is room */
savelev(fd, ledger_no(&u.uz), COUNT_SAVE);
# ifdef TUTTI_FRUTTI
/* this is in the opposite order from the real save, but savelev()
* initializes bytes_counted to 0, so doing savefruitchn() first is
* useless; the extra bflush() at the end of savelev() may increase
* bytes_counted by a couple over what the real usage will be
*/
savefruitchn(fd, COUNT_SAVE);
bflush(fd);
# endif
if (bytes_counted > freediskspace(bones)) { /* not enough room */
# ifdef WIZARD
if (wizard)
pline("Insufficient space to create bones file.");
# endif
(void) close(fd);
delete_bonesfile(&u.uz);
return;
}
co_false(); /* make sure bonesid and savefruitchn get written */
#endif /* MFLOPPY */
bwrite(fd, (genericptr_t) bonesid, 7); /* DD.nnn */
#ifdef TUTTI_FRUTTI
savefruitchn(fd, WRITE_SAVE | FREE_SAVE);
#endif
savelev(fd, ledger_no(&u.uz), WRITE_SAVE | FREE_SAVE);
bclose(fd);
compress_bonesfile();
}
int
getbones()
{
register int fd;
register int ok;
char *bonesid, oldbonesid[7];
#ifdef EXPLORE_MODE
if(discover) /* save bones files for real games */
return(0);
#endif
/* wizard check added by GAN 02/05/87 */
if(rn2(3) /* only once in three times do we find bones */
#ifdef WIZARD
&& !wizard
#endif
) return(0);
if(no_bones_level(&u.uz)) return(0);
fd = open_bonesfile(&u.uz, &bonesid);
if (fd < 0) return(0);
if((ok = uptodate(fd)) != 0){
#ifdef WIZARD
if(wizard) {
if(yn("Get bones?") == 'n') {
(void) close(fd);
compress_bonesfile();
return(0);
}
}
#endif
minit(); /* ZEROCOMP */
mread(fd, (genericptr_t) oldbonesid, 7); /* DD.nnn */
if (strcmp(bonesid, oldbonesid)) {
#ifdef WIZARD
if (wizard) {
pline("This is bones level '%s', not '%s'!",
oldbonesid, bonesid);
ok = FALSE; /* won't die of trickery */
}
#endif
trickery();
} else {
register struct monst *mtmp;
getlev(fd, 0, 0, TRUE);
/* to correctly reset named artifacts on the level */
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
resetobjs(mtmp->minvent,TRUE);
resetobjs(fobj,TRUE);
}
}
(void) close(fd);
#ifdef WIZARD
if(wizard) {
if(yn("Unlink bones?") == 'n') {
compress_bonesfile();
return(ok);
}
}
#endif
if (!delete_bonesfile(&u.uz)) {
pline("Cannot unlink bones.");
return(0);
}
return(ok);
}
/*bones.c*/